<template>
  <div class="page_root" :key="queryUpdateFlag" data-page-name="经营看板" data-page-identification="u_fqj38a73v0">
    <a-spin :spinning="pageLoading.loading" :tip="pageLoading.tip">
      <!-- begin vid_pwix3i6a8b 自定义模板_r3koyasnpg -->
      <!--      里程碑进度表弹窗-->
      <a-modal :visible="ftfState.modalVisible" title="总体经营仪表盘" width="80%" centered :footer="null" @cancel="ftfState.modalVisible = false" :mask-closable="false" destroy-on-close>
        <div class="search-radio">
          <a-radio-group v-model:value="ftfState.radioValue" button-style="solid">
            <a-radio-button value="全部">全部</a-radio-button>
            <a-radio-button value="基础信息">基础信息</a-radio-button>
            <a-radio-button value="项目阶段">项目阶段</a-radio-button>
            <a-radio-button value="其他">其他</a-radio-button>
          </a-radio-group>
        </div>
        <div class="kb-table-box-new">
          <a-table
            :columns="filteredColumns"
            :dataSource="ftfState.dataSource"
            :scroll="{ x: '1000px', y: 500 }"
            :pagination="false"
            :loading="ftfState.tableLoading"
            bordered
            @resizeColumn="handleResizeColumn"
            :showSorterTooltip="false"
            @change="handleTableChange"
            ref="tableRef"
          >
            <template #headerCell="{ column, title }">
              <template v-if="['进展', '问题&风险', '预计开始', '预计结束'].includes(title)">
                <div class="text-line-div">{{ title }}</div>
              </template>
              <template v-if="title === '项目状态'">
                <div class="text-line-div">
                  {{ title }}
                </div>
              </template>
              <template v-if="title === '工厂名称'">
                <div class="text-line-div">
                  {{ title }}
                </div>
              </template>
              <template v-if="column.dataIndex === 'riskLevel'">
                <span>
                  {{ title }}
                  <a-tooltip>
                    <template #title>
                      <p class="risk-level-tool-tip">风险等级划分：</p>
                      <p class="risk-level-tool-tip">1、保底；</p>
                      <p class="risk-level-tool-tip">2、略有风险；</p>
                      <p class="risk-level-tool-tip">3、需要冲刺；</p>
                      <p class="risk-level-tool-tip">4、暂不强推</p>
                    </template>
                    <question-circle-outlined />
                  </a-tooltip>
                </span>
              </template>
            </template>

            <template #bodyCell="{ record, text, column, index }">
              <template v-if="column.fieldType !== 'FILE' && column.fieldType">
                <div class="db-click" @dblclick="showEditStatistics(column, record, index)">{{
                                    text
                }}</div>
              </template>
              <template v-if="column.fieldType === 'FILE'">
                <div class="file-div" @dblclick="showEditStatistics(column, record, index)">
                  <template v-if="text">
                    <div v-for="(item, index) in JSON.parse(text)" :key="item.name">
                      <a-dropdown>
                        <a :title="item.name">{{ item.name }}</a>
                        <template #overlay>
                          <a-menu>
                            <a-menu-item>
                              <a-button type="link" size="small" :disabled="!item.type.startsWith('image')" @click="viewImage(item.url)">预览</a-button>
                            </a-menu-item>
                            <a-menu-item>
                              <a-button type="link" size="small" @click="downLoadFile(item)">下载</a-button>
                            </a-menu-item>
                          </a-menu>
                        </template>
                      </a-dropdown>
                    </div>
                  </template>
                  <template v-else>
                    <div class="file-div"></div>
                  </template>
                </div>
              </template>

              <template v-if="['项目阶段'].includes(column.title)">
                <div class="db-click" @dblclick="changeData(record, index)">{{ text }}</div>
              </template>
              <template v-if="column.dataIndex === 'progress'">
                <div class="progress-click" @dblclick="changeData(record, index)">
                  <a-tooltip :overlay-style="overStyle" v-if="record.progress">
                    <template #title>{{ record.progress }}</template
                    ><div class="omit-div">{{ text }} </div>
                  </a-tooltip>
                </div>
              </template>
              <template v-if="column.dataIndex === 'question'">
                <div class="question-div" @dblclick="changeData(record, index)">
                  <a-tooltip :overlay-style="overStyle" v-if="record.question">
                    <template #title
                      >{{ record.question }}【 {{ record.operator }}】【{{
                                                record.operateTime

                      }}】</template
                    ><div class="omit-div-question"
                      ><span v-if="record.question">{{ text }}【 {{ record.operator }}】【{{ record.operateTime }}】</span></div
                    >
                  </a-tooltip>
                  <!--                                    <div class="plus-icon" @click="handleAddLhwt"><PlusCircleOutlined /></div>-->
                </div>
              </template>
              <template v-if="column.dataIndex === 'productionPlan'">
                <div class="productionPlan-div">
                  <a-tooltip :overlay-style="overStyle" v-if="record.productionPlan">
                    <template #title>{{ text }}</template
                    ><div class="omit-div-productionPlan" v-if="text">{{ text }}</div>
                  </a-tooltip>
                </div>
              </template>
              <template v-if="column.dataIndex === 'customerRelationship'">
                <div class="customerRelationship-div">
                  <a-tooltip :overlay-style="overStyle" v-if="record.customerRelationship">
                    <template #title>{{ text }}</template
                    ><div class="omit-div-customerRelationship"
                      ><span v-if="text">{{ text }}</span></div
                    >
                  </a-tooltip>
                </div>
              </template>
              <template v-if="column.dataIndex === 'count'">
                {{ index + 1 }}
              </template>
              <template
                v-if="
                                    [
                                        'modelExpectStartTime',
                                        'modelExpectEndTime',
                                        'testRunExpectStartTime',
                                        'testRunExpectEndTime',
                                        'runExpectStartTime',
                                        'runExpectEndTime',
                                        'checkExpectStartTime',
                                        'checkExpectEndTime',
                                        'verifyExpectStartTime',
                                        'verifyExpectEndTime'
                                    ].includes(column.dataIndex)
                                "
              >
                <div class="db-click" @dblclick="changeData(record, index)">{{ text }}</div>
              </template>
              <template v-if="column.dataIndex === 'supportors'">
                <div class="support-div" :title="text" @dblclick="changeData(record, index)">{{
                                    text
                }}</div>
              </template>
              <template v-if="column.dataIndex === 'projectStatus'">
                <div v-if="record.projectStatus === '进行中'" class="db-click" @dblclick="changeData(record, index)" style="color: #3875ff">{{ text }}</div>
                <div v-if="record.projectStatus === '准备'" class="db-click" @dblclick="changeData(record, index)" style="color: #ffa940">{{ text }}</div>
                <div v-if="record.projectStatus === '完成'" class="db-click" @dblclick="changeData(record, index)" style="color: green">{{ text }}</div>
                <div v-if="!record.projectStatus" class="db-click" @dblclick="changeData(record, index)">{{ text }}</div>
              </template>
              <template v-if="column.dataIndex === 'projectShortName'">
                <div class="db-click-name" @dblclick="changeData(record, index)">{{ text }}</div>
              </template>
            </template>
          </a-table>
        </div>
      </a-modal>

      <!--      里程碑进度表弹窗-->
      <!--      里程碑进度表弹窗-->
      <a-modal
        :visible="ftfState.detailVisible"
        title=""
        width="1200px"
        centered
        :footer="null"
        @cancel="ftfState.detailVisible = false"
        :mask-closable="false"
        destroy-on-close
        :body-style="{
                    padding: '0'
                }"
      >
        <div class="modal-body">
          <!--                  成本统计顶部区域-->

          <div class="modal-top" v-if="typeSelectIndex === 2">
            <div class="modal-top-left">
              <div class="left-top">
                <div class="left-top-img"></div>
                <div class="left-top-msg">{{ ftfState.dataSource.projectShortName }}</div>
              </div>
              <div class="left-bottom">
                <div class="bottom-left">
                  <div class="bottom-left-item">
                    <div class="title">启动时间：</div>
                    <div class="msg">{{ ftfState.dataSource.kickOffStartTime }}</div>
                  </div>
                  <div class="bottom-left-item">
                    <div class="title">预计验收：</div>
                    <div class="msg">{{ ftfState.dataSource.expectCheckEndTime }}</div>
                  </div>
                  <div class="bottom-left-item">
                    <div class="title">项目阶段：</div>
                    <div class="msg">{{ ftfState.dataSource.milepostName }}</div>
                  </div>
                </div>
                <div class="bottom-right">
                  <div class="route"></div>
                  <div class="bottom-right-item">
                    <div class="title">成本基准：</div>
                    <div class="msg">{{ ftfState.dataSource.costBase }}人天</div>
                  </div>
                  <div class="bottom-right-item">
                    <div class="title">实际成本：</div>
                    <div class="msg">{{ ftfState.dataSource.costActual }}人天</div>
                  </div>
                  <div class="bottom-right-item">
                    <div class="title" :style="getCostColor(ftfState.dataSource.costDeviation, true)">成本偏差：</div>
                    <div class="msg" :style="getCostColor(ftfState.dataSource.costDeviation, false)">{{ getCostDiffer() }}</div>
                  </div>
                </div>
              </div>
            </div>
            <div class="modal-top-right">
              <div class="right-top">
                <div class="right-top-img"></div>
                <div class="right-top-msg">{{ ftfState.dataSource.areaName }}</div>
              </div>
              <div class="right-bottom">
                <div class="bottom-right-item">
                  <div class="title">合计成本基准：</div>
                  <div class="msg">{{ ftfState.dataSource.totalCostBase }}人天</div>
                </div>
                <div class="bottom-right-item">
                  <div class="title">累计实际成本：</div>
                  <div class="msg">{{ ftfState.dataSource.totalCostActual }}人天</div>
                </div>
                <div class="bottom-right-item">
                  <div class="title" :style="getTotalCostColor(ftfState.dataSource.totalCostDeviation, true)">累计成本偏差：</div>
                  <div class="msg" :style="getTotalCostColor(ftfState.dataSource.totalCostDeviation, false)">{{ getOverExpenditure(ftfState.dataSource.totalCostDeviation) }}</div>
                </div>
              </div>
            </div>
          </div>
          <!--                  成本统计顶部区域-->
          <!--                  任务完成顶部区域-->
          <div class="modal-top-0" v-if="typeSelectIndex === 0">
            <div class="modal-top-left-0">
              <div class="left-top-0">
                <div class="left-top-img"></div>
                <div class="left-top-msg">{{ ftfState.dataSource.projectShortName }}</div>
              </div>
              <div class="left-bottom-0">
                <div class="new-bottom">
                  <div class="bottom-left-0">
                    <div class="bottom-left-item">
                      <div class="title">启动时间：</div>
                      <div class="msg">{{ ftfState.dataSource.kickOffStartTime }}</div>
                    </div>
                    <div class="bottom-left-item">
                      <div class="title">预计验收：</div>
                      <div class="msg">{{ ftfState.dataSource.expectCheckEndTime }}</div>
                    </div>
                    <div class="bottom-left-item">
                      <div class="title">项目阶段：</div>
                      <div class="msg">{{ ftfState.dataSource.milepostName }}</div>
                    </div>
                  </div>
                  <div class="bottom-right-0">
                    <div class="route-0"></div>
                    <div class="bottom-right-item">
                      <div class="title">计划周期：</div>
                      <div class="msg">{{ ftfState.dataSource.periodBase }}天</div>
                    </div>
                    <div class="bottom-right-item">
                      <div class="title">实际周期：</div>
                      <div class="msg">{{ ftfState.dataSource.periodActual }}天</div>
                    </div>
                    <div class="bottom-right-item">
                      <div class="title" :style="getReferenceColor(ftfState.dataSource.periodDeviation, true)">进度偏差：</div>
                      <div class="msg" :style="getReferenceColor(ftfState.dataSource.periodDeviation, false)">{{ getTaskStatus(ftfState.dataSource.periodDeviation) }}</div>
                    </div>
                  </div>
                </div>
                <div class="bottom-right-last-0">
                  <div class="bottom-right-item">
                    <div class="title">主要风险：</div>
                    <div class="msg">{{ ftfState.dataSource.mainRisk || '--' }}</div>
                  </div>
                </div>
              </div>
            </div>
            <div class="modal-top-right-0">
              <div class="right-top-0">
                <div class="right-top-img"></div>
                <div class="right-top-msg-0">{{ ftfState.dataSource.areaName }}</div>
              </div>
              <div class="right-bottom-0">
                <div class="bottom-right-item-0">
                  <div class="title">合计周期基准：</div>
                  <div class="msg">{{ ftfState.dataSource.totalPeriodBase }}天</div>
                </div>
                <div class="bottom-right-item-0">
                  <div class="title">累计实际周期：</div>
                  <div class="msg">{{ ftfState.dataSource.totalPeriodActual }}天</div>
                </div>
                <div class="bottom-right-item-0">
                  <div class="title" :style="getTotalReferenceColor(ftfState.dataSource.totalPeriodDeviation, true)">累计周期偏差：</div>
                  <div class="msg" :style="getTotalReferenceColor(ftfState.dataSource.totalPeriodDeviation, false)">{{ getTotalTaskStatus(ftfState.dataSource.totalPeriodDeviation) }}</div>
                </div>
              </div>
            </div>
          </div>
          <!--                  任务完成顶部区域-->
          <!--                  资源投入顶部内容-->
          <div class="modal-top" v-if="typeSelectIndex === 1">
            <div class="modal-top-left">
              <div class="left-top">
                <div class="left-top-img"></div>
                <div class="left-top-msg">{{ ftfState.dataSource.projectShortName }}</div>
              </div>
              <div class="left-bottom">
                <div class="bottom-left">
                  <div class="bottom-left-item">
                    <div class="title">启动时间：</div>
                    <div class="msg">{{ ftfState.dataSource.kickOffStartTime }}</div>
                  </div>
                  <div class="bottom-left-item">
                    <div class="title">预计验收：</div>
                    <div class="msg">{{ ftfState.dataSource.expectCheckEndTime }}</div>
                  </div>
                  <div class="bottom-left-item">
                    <div class="title">项目阶段：</div>
                    <div class="msg">{{ ftfState.dataSource.milepostName }}</div>
                  </div>
                </div>
                <div class="bottom-right">
                  <div class="route"></div>
                  <div class="bottom-right-item">
                    <div class="title" :style="getNameColor(ftfState.dataSource.pmDevition)">项目经理：</div>
                    <div class="msg" :style="getNameColor(ftfState.dataSource.pmDevition)">
                      {{ ftfState.dataSource.pmName

                      }}{{
                                                ftfState.dataSource.pmFactoryNumber > 1
                                                    ? '(' + '兼' + ftfState.dataSource.pmFactoryNumber + ')'
                                                    : ''
                      }}</div
                    >
                  </div>
                  <div class="bottom-right-item">
                    <div class="title" :style="getNameColor(ftfState.dataSource.expertDevition)">业务专家：</div>
                    <div class="msg" :style="getNameColor(ftfState.dataSource.expertDevition)"
                      >{{ ftfState.dataSource.businessExpert

                      }}{{
                                                ftfState.dataSource.expertFactoryNumber > 1
                                                    ? '(' + '兼' + ftfState.dataSource.expertFactoryNumber + ')'
                                                    : ''
                      }}</div
                    >
                  </div>
                </div>
              </div>
            </div>
            <div class="modal-top-right">
              <div class="right-top">
                <div class="right-top-img"></div>
                <div class="right-top-msg">{{ ftfState.dataSource.areaName }}</div>
              </div>
              <div class="right-bottom">
                <div class="bottom-right-item">
                  <div class="title">项目总监：</div>
                  <div class="msg">{{ ftfState.dataSource.directorFactoryNumber }}</div>
                </div>
                <div class="bottom-right-item">
                  <div class="title" :style="getNameColor(ftfState.dataSource.pmDevition)">项目经理：</div>
                  <div class="msg" :style="getNameColor(ftfState.dataSource.pmDevition)"
                    >{{ ftfState.dataSource.pmAreaNumber

                    }}{{
                                            ftfState.dataSource.pmAreaExtraNumber > ftfState.dataSource.pmAreaNumber
                                                ? '(' + '兼' + ftfState.dataSource.pmAreaExtraNumber + ')'
                                                : ''
                    }}</div
                  >
                </div>
                <div class="bottom-right-item">
                  <div class="title" :style="getNameColor(ftfState.dataSource.expertDevition)">业务专家：</div>
                  <div class="msg" :style="getNameColor(ftfState.dataSource.expertDevition)"
                    >{{ ftfState.dataSource.expertAreaNumber

                    }}{{
                                            ftfState.dataSource.expertAreaExtraNumber >
                                            ftfState.dataSource.expertAreaNumber
                                                ? '(' + '兼' + ftfState.dataSource.expertAreaExtraNumber + ')'
                                                : ''
                    }}</div
                  >
                </div>
              </div>
            </div>
          </div>
          <!--                  资源投入顶部内容-->
          <div class="kb-table-box">
            <div class="inner-table">
              <div class="inner-top-main">
                <div class="inner-top-item">
                  <div class="item-son">
                    <div class="title">区域：</div>
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.areaName }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title">项目经理：</div>
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.pmName }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title">项目支持：</div>
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.supportors }}</div>
                  </div>
                </div>
                <div class="inner-top-item">
                  <div class="item-son">
                    <div class="title">工厂名称：</div>
                    <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.projectShortName
                    }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title">熟料算法：</div>
                    <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.clinkerAlgorithmExpert
                    }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title">正式运行持续天数：</div>
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.runDays }}</div>
                  </div>
                </div>
                <div class="inner-top-item">
                  <div class="item-son">
                    <div class="title">批次：</div>
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.batch }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title">水泥算法：</div>
                    <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.cementAlgorithmExpert
                    }}</div>
                  </div>

                  <div class="item-son">
                    <div class="title">综合样20次：</div>
                    <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.comprehensiveSample
                    }}</div>
                  </div>
                </div>
                <div class="inner-top-item">
                  <div class="item-son">
                    <div class="title">产品类型：</div>
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.productType }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title">项目阶段：</div>
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.milepostName }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title">降本空间：</div>
                    <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.expectedCostReduction
                    }}</div>
                  </div>
                </div>
                <div class="inner-top-item">
                  <div class="item-son">
                    <div class="title">项目总监：</div>
                    <div class="msg">{{
                                            ftfState.dataSource.projectProgress?.projectDirector
                    }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title">项目状态：</div>
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.projectStatus }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title">商务：</div>
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.preSaleManager }}</div>
                  </div>
                </div>
                <div class="inner-top-item">
                  <div class="item-son">
                    <div class="title">水泥专家：</div>
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.businessExpert }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title">
                      <a-tooltip>
                        <template #title>
                          <p class="risk-level-tool-tip">风险等级划分：</p>
                          <p class="risk-level-tool-tip">1、保底；</p>
                          <p class="risk-level-tool-tip">2、略有风险；</p>
                          <p class="risk-level-tool-tip">3、需要冲刺；</p>
                          <p class="risk-level-tool-tip">4、暂不强推</p></template
                        >
                        <QuestionCircleOutlined /> </a-tooltip
                      >风险等级：</div
                    >
                    <div class="msg">{{ ftfState.dataSource.projectProgress?.riskLevel }}</div>
                  </div>
                  <div class="item-son">
                    <div class="title"></div>
                    <div class="msg"></div>
                  </div>
                </div>
              </div>
              <div class="inner-row">
                <div class="title">进展：</div>
                <div class="msg">
                  <div
                    v-for="(item, index) in handlerGetSpace(
                                            ftfState.dataSource.projectProgress?.progress
                                        )"
                  >
                    {{ item?.trim() }}
                  </div></div
                >
              </div>
              <div class="inner-row">
                <div class="title">问题&风险：</div>
                <div class="msg">
                  <div
                    v-for="(item, index) in handlerGetSpace(
                                            ftfState.dataSource.projectProgress?.question
                                        )"
                  >
                    {{ item?.trim() }}
                  </div>
                </div>
              </div>
              <div class="inner-row">
                <div class="title">生产计划：</div>
                <div class="msg">{{ ftfState.dataSource.projectProgress?.productionPlan }}</div>
              </div>
              <div class="inner-row">
                <div class="title">客情关系：</div>
                <div class="msg">
                  <div
                    v-for="(item, index) in handlerGetSpace(
                                            ftfState.dataSource.projectProgress?.customerRelationship
                                        )"
                  >
                    {{ item?.trim() }}
                  </div>
                </div>
              </div>
              <div class="inner-bottom"></div>
              <a-table
                style="margin-top: 8px"
                :columns="columnState.newColumns"
                :dataSource="ftfState.dataSource.timeList"
                :scroll="{ x: '1000px', y: 700 }"
                :pagination="false"
                :loading="ftfState.tableLoading"
                bordered
                @resizeColumn="handleResizeColumn"
                :showSorterTooltip="false"
                @change="handleTableChange"
                ref="tableRef"
              />
            </div>
          </div>
        </div>
      </a-modal>

      <!--      里程碑进度表弹窗-->
      <div class="main-content" id="mainContent">
        <div class="top-title">
          <span>经营地图看板</span>
        </div>
        <ul class="legend" v-if="typeSelectIndex === 0 || typeSelectIndex === 1">
          <li @click="onChangelegends(0)" :class="{ gray: legendsDot[0] }">
            <i class="img icon icon-green"></i>
            偏差度20%以内
          </li>
          <li @click="onChangelegends(1)" :class="{ gray: legendsDot[1] }">
            <i class="img icon icon-yellow"></i>
            {{ typeSelectIndex === 0 ? '偏差度21%-40%' : '偏差度21%-50%' }}
          </li>
          <li @click="onChangelegends(2)" :class="{ gray: legendsDot[2] }">
            <i class="img icon icon-red"></i>
            {{ typeSelectIndex === 0 ? '偏差度40%以上' : '偏差度50%以上' }}
          </li>
        </ul>
        <ul class="legend" v-else>
          <li @click="onChangelegends(0)" :class="{ gray: legendsDot[0] }">
            <i class="img icon icon-green"></i>
            未超支
          </li>
          <li @click="onChangelegends(2)" :class="{ gray: legendsDot[2] }">
            <i class="img icon icon-red"></i>
            超支
          </li>
        </ul>
        <div class="content">
          <div class="left-geo">
            <ul class="typeSels">
              <li v-for="(item, index) in typeList" :key="index" @click="onChangeType(index)" :class="{ action: index === typeSelectIndex }">{{ item.itemName }}</li>
              <div class="priority-div">
                <a-form-item label="优先级">
                  <a-select
                    style="width: 100px"
                    v-model:value="newState.priority"
                    :allow-clear="false"
                    @change="changeSymbelSize"
                    :options="[
                                            {
                                                label: '全部',
                                                value: '全部'
                                            },
                                            {
                                                label: '高',
                                                value: '高'
                                            },
                                            {
                                                label: '中',
                                                value: '中'
                                            },
                                            {
                                                label: '低',
                                                value: '低'
                                            }
                                        ]"
                    allow-clear
                    placeholder="请选择"
                  />
                </a-form-item>
              </div>
            </ul>

            <div class="proAreaSels">
              <ul :class="{ unexpend: !expends.pro }">
                <div class="name" @click="onExpends('pro')">
                  <i class="arrow-right icon"></i>
                  <i class="img icon show-active icon-pro-sel"></i>
                  <i class="img icon hide-active icon-pro"></i>

                  产品线
                </div>
                <li
                  v-for="(item, index) in proList"
                  :key="index"
                  @click="onChangeProLines(index)"
                  :class="{
                                        active: index === proSelectIndex,
                                        disabled: index > 0 && (typeSelectIndex === 1 || typeSelectIndex === 2)
                                    }"
                >
                  <i class="img icon show-active icon-data-sel"></i>
                  <i class="img icon hide-active icon-data"></i>
                  {{ item.itemName }}
                </li>
              </ul>
              <ul :class="{ unexpend: !expends.area }">
                <div class="name" @click="onExpends('area')">
                  <i class="arrow-right icon"></i>
                  <i class="img icon show-active icon-area-sel"></i>
                  <i class="img icon hide-active icon-area"></i>
                  区域
                </div>
                <li v-for="(item, index) in areaList" :key="index" :class="{ active: index === areaSelIndex }">
                  <i class="img icon show-active icon-data-sel"></i>
                  <i class="img icon hide-active icon-data"></i>
                  <span style="cursor: pointer; width: 120px" @click="onChangeArea(index)">{{
                                        item.itemName
                  }}</span>
                  <i class="img icon show-active icon-more-sel" style="margin-left: 10px; cursor: pointer" @click="getLcbData(null, '水泥配料', item.itemName)"></i>
                  <i class="img icon hide-active icon-more" style="margin-left: 10px; cursor: pointer" @click="getLcbData(null, '水泥配料', item.itemName)"></i>
                </li>
              </ul>
            </div>
          </div>
          <div class="echarts-content" :style="mainStyle">
            <div class="img china-map-bg"></div>
            <!--        <img src="http://10.40.0.33:9001/file-storage/487396325012760576-source.svg" class="china-map-bg" alt="" />-->
            <a-spin :spinning="loadingStatus" tip="数据正在加载...">
              <div class="echarts-main" id="echarts-chinamap"></div>
            </a-spin>
          </div>
        </div>
      </div>

      <!-- end vid_pwix3i6a8b 自定义模板_r3koyasnpg -->
      <!-- begin vid_z354kcjic1 图片_7j0nyi479u -->
      <al-image
        v-if="false"
        class="vid_z354kcjic1"
        :emptyImgSrc="''"
        :src="vid_z354kcjic1_props.src"
      />
      <!-- end vid_z354kcjic1 图片_7j0nyi479u -->
      <!-- begin vid_crznpxme1j 图片_f7l2frg8h7 -->
      <al-image
        v-if="false"
        class="vid_crznpxme1j"
        :emptyImgSrc="''"
        :src="vid_crznpxme1j_props.src"
      />
      <!-- end vid_crznpxme1j 图片_f7l2frg8h7 -->
    </a-spin>
  </div>
</template>
<script setup lang="tsx">
  import {
      h, ref, reactive, toRaw, markRaw, watch, computed,
      onBeforeMount, onMounted, onBeforeUnmount, onUnmounted, onActivated, onDeactivated
    } from "vue";
    import { useRoute, useRouter } from 'vue-router';
    const router = useRouter();
    const route = useRoute();
    import { get, post, put, del, request, requestWithHeaders } from '@/utils/http/Axios';
    import { cloneDeep, localGet, merge, getDifferenceArray, traversalTreeStructure, checkCaseCondition, renderStringInTemplate, handleBreadcrumbJump, throttle, permission, getComponentParamsValue } from '@/utils/index';
    import { isNullOrEmpty, isEmptyArr, isNullOrUnDef, isContained, isArray, isEmpty, isObject } from '@/utils/is';
    import dayjs from 'dayjs';
    import { getPagePcChartsDataSourceConvert } from '@/utils/chart';
    import { message, notification, Modal } from 'ant-design-vue'
    import { propertyFormatByNumber, propertyFormatByPercentage, propertyFormatByDate, parseSubFromDataList } from '@/utils/format';
    import colorTheme from '@/design/custom-theme.json';
    
    import UserTableRecords from '@/model/UserTableRecords';
    import { getAppBaseUrl } from '@/utils/index';
    import { sendToken } from "@/hooks/useIframeToken";
    import { useSystemStore } from "@/store/modules/system";
    const systemStore = useSystemStore();
    



      // 获取传入的流程ID和组件参数
      const props = defineProps({
            'processInstanceId': {
            type: [String,Number,Boolean],
            default: undefined,
        },
      })
      const immediateWatch = (source, callback) => {
        watch(source, callback, {deep: true,immediate: true })
      }



  /* -------------------------- 属性定义 -------------------------- */

      const setTimeOutList = [];
      const pageLoading = reactive({
        loading: false,
        tip: undefined
      });
      const authInfo = localGet('app-user-store');
// 图片 http://10.40.0.33:9001/file-storage/493887559979984896.png
import vid_z354kcjic1_imageUrl from '@/assets/images/1fbfe9e6c143987152a1e8c8d0c7a098.png'

    const vid_z354kcjic1_props = reactive({
          src: vid_z354kcjic1_imageUrl,
  })
// 图片 http://10.40.0.33:9001/file-storage/493904223171733504.png
import vid_crznpxme1j_imageUrl from '@/assets/images/71f2aa0b9331cd4bf275859992e21f52.png'

    const vid_crznpxme1j_props = reactive({
          src: vid_crznpxme1j_imageUrl,
  })



      // 处理校验
      const setSubFormName =(parentInfo, name)=>{
        return [parentInfo.parents, parentInfo.cycleIndex, name];
      }


  /* ========================== 属性定义 ========================== */


  /* -------------------------- 元素数据引用 -------------------------- */


  /* ========================== 元素数据引用 ========================== */


  /* -------------------------- 页面数据 -------------------------- */


  /* ========================== 页面数据 ========================== */



  /* -------------------------- 响应 -------------------------- */

  /* ========================== 响应 ========================== */


  /* -------------------------- 函数 -------------------------- */

  /* ========================== 函数 ========================== */


  /* -------------------------- 页面参数 -------------------------- */

    const pageParameter_state = reactive({
        'processInstanceId': props.processInstanceId ?? route.query.processInstanceId,
    })

  /* ========================== 页面参数 ========================== */


  /* -------------------------- 组件事件处理方法 -------------------------- */

    // ---------------------------- 组件数据同步 ----------------------------

    // ============================ 组件数据同步 ============================


  /* ========================== 组件事件处理方法 ========================== */


  /* -------------------------- 生命周期 -------------------------- */
  // 用于参数变更后重新执行自定义指令
      const queryUpdateFlag = ref(0);
      onMounted(() => { ;

    });

    onUnmounted(() => {
      // 销毁定时器
      setTimeOutList.forEach(({ repeat, timer }) => {
        repeat ?  clearInterval(timer): clearTimeout(timer);
      });
    });

  /* ========================== 生命周期 ========================== */


  /* -------------------------- 数据关联处理 -------------------------- */





  /* -------------------------- 表单数据同步 -------------------------- */
  /* ========================== 表单数据同步 ========================== */

  /* ========================== 数据关联处理 ========================== */


  /* -------------------------- 不同组件自定义的处理逻辑 -------------------------- */

  /* ========================== 不同组件自定义的处理逻辑 ========================== */


  // ================================定制化逻辑========================================
   import { nextTick } from 'vue'
      import * as echarts from 'echarts'
      // import chinaJson from './china'
      const chinaJson = {}
      const chartBox = ref(null)
      const loadingStatus = ref(false)
      const areaList = ref([
          // { itemName: '西南水泥', children: [{ itemName: '黑龙江省' }, { itemName: '云南省' }] },
      ])
      const proList = ref([
          // { itemName: '西南水泥', children: [{ itemName: '黑龙江省' }, { itemName: '云南省' }] },
      ])
      const dataId = ref('echarts-chinaMap')
      const proSelectIndex = ref(0)
      const areaSelIndex = ref(null)
      const typeSelectIndex = ref(0)
      const expends = ref({
          pro: true,
          area: true
      })
      const onExpends = type => {
          expends.value[type] = !expends.value[type]
          // if (type == 'pro') {
          //     proSelectIndex.value = null
          // }
          // if (type == 'area') {
          //     areaSelIndex.value = null
          // }
      }
      // 计算属性 mergeoptions
      const mergeoptions = computed(() => {
          const defaultOpt = {}
          return {
              ...defaultOpt,
              ...options.value
          }
      })

      const mainStyle = ref(document.body.offsetWidth)
      const proLineDatas = ref([])
      const typeList = ref([
          { itemName: '任务完成', type: 'TASK_DEVIATION' },
          { itemName: '资源投入', type: 'RESOURCE_DEVIATION' },
          { itemName: '成本统计', type: 'COST_DEVIATION' }
      ])
      const options = computed(() => ({
          // roam: true, // 开启鼠标缩放和平移漫游
          // zoom: 1, // 初始缩放比例
          // scaleLimit: { // 缩放的比例限制
          //     min: 1, // 最小缩放比例
          //     max: 20 // 最大缩放比例
          // },
          tooltip: {
              show: true,
              position: 'top',
              className: 'map-dialog',
              renderMode: 'html',
              formatter(params) {
                  return params.data.factoryName
                  // return `<div class="status-${params.data.legendsType}">${params.data.factoryName}<div class="value"><i></i>${params.data.deviation}</div></div>`
              }
          },
          grid: {
              top: 0,
              left: 0,
              right: 0,
              bottom: 0
          },
          geo: [
              {
                  // top:530,
                  map: 'chinaBoundary',
                  // 避免边框选中，设置不响应事件
                  silent: true,
                  emphasis: {
                      disabled: true
                  },
                  itemStyle: {
                      normal: {
                          // borderWidth: 5,
                          areaColor: 'rgba(0, 0, 0, 0)',
                          borderColor: 'rgba(255, 255, 255, 0)'
                      }
                  }
              }
          ],
          series: [
              {
                  type: 'map',
                  silent: true,
                  selectedMode: false,
                  map: 'china',
                  coordinateSystem: 'geo',
                  label: {
                      show: true,
                      color: '#333',
                      fontSize: 12
                  },
                  itemStyle: {
                      normal: {
                          areaColor: 'rgba(0, 0, 0, 0)',
                          borderColor: 'rgba(0, 0, 0, 0)',
                          borderJoin: 'round'
                      },
                      emphasis: {
                          label: {
                              show: true,
                              color: '#3a76ff',
                              fontSize: 12
                          },
                          borderWidth: 1.4,
                          borderJoin: 'round',
                          areaColor: 'rgba(56,177,255,.1)',
                          borderColor: '#3a76ff' // 设置省份分界线的颜色
                      }
                  }
              },

              {
                  type: 'effectScatter',
                  coordinateSystem: 'geo',
                  data: proLineDatas?.value.filter(item => !legendsDot.value[item.legendsType]) || [],
                  // 标记点样式
                  // symbolSize: 7,
                  // symbolSize: item => {
                  //     // 计算优先级
                  //   if (newState.priority === '全部') {
                  //     return 7; // 默认大小为 7
                  //   }
                  //     if (item.priority === newState.priority) {
                  //         return 15 // 被选中优先级的大小
                  //     } else {
                  //         return 5 // 其他优先级的较小尺寸
                  //     }
                  // },
                  symbolSize: function (val, params) {
                      if (newState.priority === '全部') {
                          return 7 // 默认大小为 7
                      }
                      // 检查是否存在符合当前优先级的数据
                      let hasMatchingData = false
                      for (let i = 0; i < proLineDatas.value.length; i++) {
                          if (proLineDatas.value[i].priority === newState.priority) {
                              hasMatchingData = true
                              break
                          }
                      }

                      if (!hasMatchingData) {
                          // 没有找到对应优先级的数据，给出提示
                          // 这里可以根据实际情况使用更合适的 message 提示方式，例如使用弹窗库
                          // 比如使用 element-ui 的 MessageBox
                          // this.$messagebox('提示', '无该优先级数据');
                          return 0 // 大小不变，使用默认大小
                      }

                      if (params.data.priority === newState.priority) {
                          return 7 // 被选中优先级的大小
                      } else {
                          return 0 // 其他优先级的较小尺寸
                      }
                      // if (params.data.priority === newState.priority) {
                      //     return 10 // 被选中优先级的大小
                      // } else {
                      //     return 5 // 其他优先级的较小尺寸
                      // }
                  },
                  showEffectOn: 'render'
              }
          ]
      }))

      //   初始化图表
      const initChartBox = () => {
          chartBox.value = echarts.init(document.getElementById('echarts-chinamap'), null, {
              renderer: 'svg',
              devicePixelRatio: 2
          })
          window.addEventListener('resize', () => {
              setMainStyle()
              chartBox.value?.resize()
          })
          renderChart()
          chartBox.value.on('click', bindMapClik)
      }

      //   绑定点击
      const bindMapClik = params => {
          if (params.componentType === 'series' && params.data) {
              const data = params.data
              getData(data, data.projectId, proList.value[proSelectIndex.value].itemName)
          }
      }

      //   渲染
      const renderChart = () => {
          if (!chartBox.value) {
              initChartBox()
              chartBox.value?.setOption(mergeoptions.value)
          } else {
              chartBox.value?.setOption(mergeoptions.value)
          }
      }

      // 切换分类
      const onChangeType = index => {
          if (index === typeSelectIndex.value) return
          typeSelectIndex.value = index
          proSelectIndex.value = 0
          onGetProDatas()
      }
      //切换产线
      const onChangeProLines = (index, type) => {
          if (index > 0 && typeSelectIndex.value === 1) {
              return
          }
          proSelectIndex.value = index
          areaSelIndex.value = null
          expends.value.pro = true
          onGetProDatas()
      }

      // 切换区域
      const onChangeArea = index => {
          expends.value.area = true
          toogleHighlight('downplay', areaSelIndex.value || 0)
          nextTick(() => {
              areaSelIndex.value = index
              toogleHighlight('highlight', index)
          })
      }

      // 切换区域
      const legendsDot = ref([false, false, false])
      const onChangelegends = index => {
          legendsDot.value[index] = !legendsDot.value[index]
          renderChart()
      }

      //   切换区域
      const toogleHighlight = (type = 'highlight', index) => {
          const area = areaList.value[index]
          area.children.forEach(item => {
              const name = item.itemName.replace(/[省市自治区]/g, '')
              chartBox.value?.dispatchAction({
                  type,
                  name: name
              })
          })
      }

      //
      const ongetoperation = params => {
          loadingStatus.value = true
          post('/solution-ppm/api/v2/built-in-system-ppm/project/dashboard/operation/search', params)
              .then(res => {
                  const colors = ['#52c41a', '#ffc500', '#f5222d']
                  const colors1 = ['#52c41a', '#f5222d']
                  proLineDatas.value =
                      res.data?.map(item => {
                          const index = Number(item.deviation) < 21 ? 0 : Number(item.deviation) > 50 ? 2 : 1
                          const index1 = Number(item.deviation) > 0 ? 1 : 0
                          // 这俩测试用
                          const randomCost = Math.floor(Math.random() * 3)
                          // 这俩测试用
                          return {
                              ...item,
                              value: [item.longuide, item.latitude],
                              itemStyle: {
                                  // color: colors[index]
                                  color: typeSelectIndex.value === 2 ? colors1[index1] : colors[index]
                              },
                              rippleEffect: {
                                  brushType: 'fill',
                                  scale: 3,
                                  number: 2,
                                  period: 3,
                                  // color: colors[index]
                                  color: typeSelectIndex.value === 2 ? colors1[index1] : colors[index]
                              },
                              legendsType: index,
                              // 下面俩测试使用
                              cost: randomCost
                              // 测试使用
                          }
                      }) || []
                  renderChart()
                  loadingStatus.value = false
              })
              .catch(error => {
                  console.error('失败:', error)
              })
      }

      const onGetProDatas = () => {
          ongetoperation({
              productLine: proList.value[proSelectIndex.value].itemName,
              type: typeList.value[typeSelectIndex.value].type
          })
      }

      const onGetChinaJson = async params => {
          if (sessionStorage.getItem('chinaMapJson')) {
              return JSON.parse(sessionStorage.getItem('chinaMapJson'))
          }
          const res = await get('/solution-ppm/api/v2/built-in-system-ppm/project/dashboard/operation/china')
          sessionStorage.setItem('chinaMapJson', res.data)
          return JSON.parse(res.data)
      }

      const onAreaList = params => {
          if (sessionStorage.getItem('onAreaList')) {
              return JSON.parse(sessionStorage.getItem('onAreaList'))
          }
          get('/solution-ppm/api/v2/built-in-system-ppm/dictionary/search_tree/OPERATION.AREA')
              .then(res => {
                  areaList.value = res.data || []
                  sessionStorage.setItem('areaList', JSON.stringify(res.data))
              })
              .catch(error => {
                  console.error('失败:', error)
              })
      }

      const getProList = params => {
          get('/solution-ppm/api/v2/built-in-system-ppm/dictionary/search/OPERATION.PRODUCT_LINE')
              .then(res => {
                  proList.value = res.data || []
                  if (res.data && res.data[0]) {
                      onChangeProLines(0)
                  }
              })
              .catch(error => {
                  console.error('失败:', error)
              })
      }

      const init = async () => {
          setMainStyle()
          const chinaJsonData = (await onGetChinaJson()) || chinaJson
          echarts.registerMap('china', chinaJsonData)
          echarts.registerMap('chinaBoundary', chinaJsonData)
          initChartBox()
          onAreaList()
          getProList()
      }

      onMounted(() => {
          init()
      })
      const setMainStyle = () => {
          const dom = document.getElementById('mainContent')
          let cliWidth = dom.offsetWidth
          let cliHeight = dom.offsetHeight
          let contW = 1126
          let contH = 851
          let w = cliWidth / contW
          let h = cliHeight / contH
          let per = w < h ? w : h
          mainStyle.value = `transform: scale(${per * 1.15} , ${per * 1.15 * 0.89});transform-origin:center;margin-top:${
              (contH * (per - 1)) / 2
          }px;`
      }

      onBeforeUnmount(() => {
          if (chartBox.value) {
              chartBox.value.dispose()
              chartBox.value = null
              window.removeEventListener('resize', () => {
                  chartBox.value?.resize()
              })
          }
      })

      const watchMergeOptions = watch(
          mergeoptions,
          () => {
              renderChart()
          },
          { deep: true }
      )

      // 暴露给模板的变量和函数
      defineExpose({
          areaList,
          areaSelIndex,
          onChangeArea,
          toogleHighlight
      })
      // 原里程碑进度部分
      const filteredColumns = computed(() => {
          return columnState.columns
              .map(column => {
                  const updatedColumn = {
                      ...column,
                      children:
                          column.children && Array.isArray(column.children)
                              ? column.children.filter(child => child.visible)
                              : []
                  }

                  if (updatedColumn.children.length === 0 && column.children?.length > 0) {
                      updatedColumn.visible = false
                  }

                  return updatedColumn.visible === false ? null : updatedColumn
              })
              .filter(Boolean)
      })
      const overStyle = ref({
          maxWidth: '300px',
          fontSize: '16px'
      })
      const customOkCellStyle = () => {
          return {
              style: {
                  padding: '4px 16px'
              }
          }
      }
      const handleResizeColumn = (w, col) => {
          const width = w - 50 // 确保宽度被计算并且减去额外空间

          // 根据列标题来确定不同的 div
          let div = null
          if (col.title === '进展') {
              div = document.querySelectorAll('.omit-div')
          } else if (col.title.includes('问题&风险')) {
              div = document.querySelectorAll('.omit-div-question')
          } else if (col.title === '生产计划') {
              div = document.querySelectorAll('.omit-div-productionPlan')
          } else if (col.title === '客情关系') {
              div = document.querySelectorAll('.omit-div-customerRelationship')
          }

          // 如果找到了对应的 div，更新其宽度
          if (div.length > 0) {
              div.forEach(item => {
                  item.style.width = `${width}px`
              })
              overStyle.value.maxWidth = `${width}px` // 更新 tooltip 最大宽度
          }

          // 更新 columnState 中的列宽
          columnState.columns = columnState.columns.map(item => {
              if (item.dataIndex === col.dataIndex) {
                  return { ...item, width: w } // 更新该列的宽度
              }
              return item
          })

          // 如果列有子列，确保子列也能根据父列的宽度进行更新
          if (col.children) {
              col.children.forEach(child => {
                  columnState.columns = columnState.columns.map(item => {
                      if (item.dataIndex === child.dataIndex) {
                          return { ...item, width: w } // 更新子列的宽度
                      }
                      return item
                  })
              })
          }
      }
      function getLcbData(id, type, areaName) {
          if (type !== '水泥配料') {
              return
          }
          ftfState.filter.projectId = id
          ftfState.tableLoading = true
          post('/solution-ppm/api/v2/built-in-system-ppm/project_progress/search ', {
              ...ftfState.filter,
              areaName: !id ? [areaName] : null,
              customSort: ftfState.filter.customSort
          })
              .then(data => {
                  if (data.code !== 200) {
                      ftfState.dataSource = []
                      message.error(data.message)
                      return
                  }

                  ftfState.dataSource = data.data.map(({ customDataMap, ...rest }) => ({
                      ...rest,
                      ...customDataMap // 解构并展开 customDataMap 的内容
                  }))
                  ftfState.modalVisible = true
              })
              .finally(() => {
                  ftfState.tableLoading = false
              })
      }
      const columnState = reactive({
          columns: [
              {
                  title: '序号',
                  dataIndex: 'count',
                  align: 'center',
                  width: 50,
                  fixed: 'left',
                  ellipsis: true
              },
              {
                  'title': '区域',
                  'dataIndex': 'areaName',
                  ellipsis: true,
                  width: 120,
                  fixed: 'left',
                  align: 'center'
              },
              {
                  title: '工厂名称',
                  dataIndex: 'projectShortName',
                  ellipsis: true,
                  width: 130,
                  fixed: 'left',
                  align: 'center'
              },

              {
                  title: '批次',
                  dataIndex: 'batch',
                  ellipsis: true,
                  width: 80,
                  align: 'center',
                  visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
              },

              {
                  title: '产品类型',
                  dataIndex: 'productType',
                  ellipsis: true,
                  width: 80,
                  align: 'center',
                  visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
              },
              {
                  title: '项目总监',
                  dataIndex: 'projectDirector',
                  ellipsis: true,
                  align: 'center',
                  width: 80,
                  visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
              },
              {
                  title: '水泥专家',
                  dataIndex: 'businessExpert',
                  align: 'center',
                  ellipsis: true,
                  width: 80,
                  visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
              },
              {
                  title: '项目经理',
                  dataIndex: 'pmName',
                  align: 'center',
                  ellipsis: true,
                  width: 80,
                  customCell: customOkCellStyle,
                  visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
              },
              {
                  title: '熟料算法',
                  dataIndex: 'clinkerAlgorithmExpert',
                  align: 'center',
                  ellipsis: true,
                  width: 80,
                  customCell: customOkCellStyle,
                  visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
              },
              {
                  title: '水泥算法',
                  dataIndex: 'cementAlgorithmExpert',
                  align: 'center',
                  ellipsis: true,
                  width: 80,
                  customCell: customOkCellStyle,
                  visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
              },
              {
                  title: '商务',
                  dataIndex: 'preSaleManager',
                  align: 'center',
                  ellipsis: true,
                  width: 80,
                  customCell: customOkCellStyle,
                  visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
              },

              {
                  title: '数据积累',
                  ellipsis: true,
                  align: 'center',
                  visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                  children: [
                      {
                          title: '计划开始',
                          dataIndex: 'collectionMappingPlanStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.collectionMappingPlanStartTime)
                              const timeB = dayjs(b.collectionMappingPlanStartTime)

                              // 处理空值，确保空值排在最后
                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1 // a 是无效时间，排到后面
                              if (!timeB.isValid()) return -1 // b 是无效时间，排到后面

                              // 有效的时间做正常排序
                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '计划结束',
                          dataIndex: 'collectionMappingPlanEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.collectionMappingPlanEndTime)
                              const timeB = dayjs(b.collectionMappingPlanEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际开始',
                          dataIndex: 'collectionMappingActualStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.collectionMappingActualStartTime)
                              const timeB = dayjs(b.collectionMappingActualStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },

                      {
                          title: '实际结束',
                          dataIndex: 'collectionMappingActualEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.collectionMappingActualEndTime)
                              const timeB = dayjs(b.collectionMappingActualEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计开始',
                          dataIndex: 'collectionMappingExpectStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.collectionMappingExpectStartTime)
                              const timeB = dayjs(b.collectionMappingExpectStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计结束',
                          dataIndex: 'collectionMappingExpectEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.collectionMappingExpectEndTime)
                              const timeB = dayjs(b.collectionMappingExpectEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      }
                  ]
              },

              {
                  title: '自学习表数据确认',
                  ellipsis: true,
                  align: 'center',
                  visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                  children: [
                      {
                          title: '计划开始',
                          dataIndex: 'processingTableConfirmPlanStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.processingTableConfirmPlanStartTime)
                              const timeB = dayjs(b.processingTableConfirmPlanStartTime)

                              // 处理空值，确保空值排在最后
                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1 // a 是无效时间，排到后面
                              if (!timeB.isValid()) return -1 // b 是无效时间，排到后面

                              // 有效的时间做正常排序
                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '计划结束',
                          dataIndex: 'processingTableConfirmPlanEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.processingTableConfirmPlanEndTime)
                              const timeB = dayjs(b.processingTableConfirmPlanEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际开始',
                          dataIndex: 'processingTableConfirmActualStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.processingTableConfirmActualStartTime)
                              const timeB = dayjs(b.processingTableConfirmActualStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },

                      {
                          title: '实际结束',
                          dataIndex: 'processingTableConfirmActualEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.processingTableConfirmActualEndTime)
                              const timeB = dayjs(b.processingTableConfirmActualEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计开始',
                          dataIndex: 'processingTableConfirmExpectStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.processingTableConfirmExpectStartTime)
                              const timeB = dayjs(b.processingTableConfirmExpectStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计结束',
                          dataIndex: 'processingTableConfirmExpectEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.processingTableConfirmExpectEndTime)
                              const timeB = dayjs(b.processingTableConfirmExpectEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      }
                  ]
              },
              {
                  title: '数据建模',
                  ellipsis: true,
                  align: 'center',
                  visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                  children: [
                      {
                          title: '计划开始',
                          dataIndex: 'modelStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.modelStartTime)
                              const timeB = dayjs(b.modelStartTime)

                              // 处理空值，确保空值排在最后
                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1 // a 是无效时间，排到后面
                              if (!timeB.isValid()) return -1 // b 是无效时间，排到后面

                              // 有效的时间做正常排序
                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '计划结束',
                          dataIndex: 'modelEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.modelEndTime)
                              const timeB = dayjs(b.modelEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际开始',
                          dataIndex: 'modelActualStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.modelActualStartTime)
                              const timeB = dayjs(b.modelActualStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },

                      {
                          title: '实际结束',
                          dataIndex: 'modelActualEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.modelActualEndTime)
                              const timeB = dayjs(b.modelActualEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计开始',
                          dataIndex: 'modelExpectStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.modelExpectStartTime)
                              const timeB = dayjs(b.modelExpectStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计结束',
                          dataIndex: 'modelExpectEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.modelExpectEndTime)
                              const timeB = dayjs(b.modelExpectEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      }
                  ]
              },
              {
                  title: '试运行',
                  ellipsis: true,
                  align: 'center',
                  visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                  children: [
                      {
                          title: '计划开始',
                          dataIndex: 'testRunStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.testRunStartTime)
                              const timeB = dayjs(b.testRunStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },

                      {
                          title: '计划结束',
                          dataIndex: 'testRunEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.testRunEndTime)
                              const timeB = dayjs(b.testRunEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际开始',
                          dataIndex: 'testRunActualStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.testRunActualStartTime)
                              const timeB = dayjs(b.testRunActualStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际结束',
                          dataIndex: 'testRunActualEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.testRunActualEndTime)
                              const timeB = dayjs(b.testRunActualEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计开始',
                          dataIndex: 'testRunExpectStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.testRunExpectStartTime)
                              const timeB = dayjs(b.testRunExpectStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计结束',
                          dataIndex: 'testRunExpectEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.testRunExpectEndTime)
                              const timeB = dayjs(b.testRunExpectEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      }
                  ]
              },
              {
                  title: '正式运行',
                  ellipsis: true,
                  align: 'center',
                  visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                  children: [
                      {
                          title: '计划开始',
                          dataIndex: 'runStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.runStartTime)
                              const timeB = dayjs(b.runStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },

                      {
                          title: '计划结束',
                          dataIndex: 'runEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.runEndTime)
                              const timeB = dayjs(b.runEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际开始',
                          dataIndex: 'runActualStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.runActualStartTime)
                              const timeB = dayjs(b.runActualStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际结束',
                          dataIndex: 'runActualEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.runActualEndTime)
                              const timeB = dayjs(b.runActualEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计开始',
                          dataIndex: 'runExpectStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.runExpectStartTime)
                              const timeB = dayjs(b.runExpectStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计结束',
                          dataIndex: 'runExpectEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.runExpectEndTime)
                              const timeB = dayjs(b.runExpectEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      }
                  ]
              },
              {
                  title: '验证',
                  ellipsis: true,
                  align: 'center',
                  visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                  children: [
                      {
                          title: '计划开始',
                          dataIndex: 'verifyStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.verifyStartTime)
                              const timeB = dayjs(b.verifyStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },

                      {
                          title: '计划结束',
                          dataIndex: 'verifyEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.verifyEndTime)
                              const timeB = dayjs(b.verifyEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际开始',
                          dataIndex: 'verifyActualStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.verifyActualStartTime)
                              const timeB = dayjs(b.verifyActualStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际结束',
                          dataIndex: 'verifyActualEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.verifyActualEndTime)
                              const timeB = dayjs(b.verifyActualEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计开始',
                          dataIndex: 'verifyExpectStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.verifyExpectStartTime)
                              const timeB = dayjs(b.verifyExpectStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计结束',
                          dataIndex: 'verifyExpectEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.verifyExpectEndTime)
                              const timeB = dayjs(b.verifyExpectEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      }
                  ]
              },
              {
                  title: '验收',
                  ellipsis: true,
                  align: 'center',
                  visible: computed(() => ['全部', '项目阶段'].includes(ftfState.radioValue)),
                  children: [
                      {
                          title: '计划开始',
                          dataIndex: 'checkStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.checkStartTime)
                              const timeB = dayjs(b.checkStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },

                      {
                          title: '计划结束',
                          dataIndex: 'checkEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.checkEndTime)
                              const timeB = dayjs(b.checkEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际开始',
                          dataIndex: 'checkActualStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.checkActualStartTime)
                              const timeB = dayjs(b.checkActualStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '实际结束',
                          dataIndex: 'checkActualEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.checkActualEndTime)
                              const timeB = dayjs(b.checkActualEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计开始',
                          dataIndex: 'checkExpectStartTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.checkExpectStartTime)
                              const timeB = dayjs(b.checkExpectStartTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      },
                      {
                          title: '预计结束',
                          dataIndex: 'checkExpectEndTime',
                          ellipsis: true,
                          align: 'center',
                          width: 150,
                          sorter: (a, b) => {
                              const timeA = dayjs(a.checkExpectEndTime)
                              const timeB = dayjs(b.checkExpectEndTime)

                              if (!timeA.isValid() && !timeB.isValid()) return 0
                              if (!timeA.isValid()) return 1
                              if (!timeB.isValid()) return -1

                              return timeA - timeB
                          },
                          visible: true
                      }
                  ]
              },

              {
                  title: '项目阶段',
                  dataIndex: 'milepostName',
                  sorter: true,
                  ellipsis: true,
                  align: 'center',
                  width: 80,
                  sorter: true,
                  visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
              },
              {
                  title: '项目状态',
                  dataIndex: 'projectStatus',
                  ellipsis: true,
                  align: 'center',
                  width: 80,
                  visible: computed(() => ['全部', '基础信息'].includes(ftfState.radioValue))
              },
              {
                  title: '进展',
                  dataIndex: 'progress',
                  ellipsis: true,
                  resizable: true,
                  align: 'center',
                  width: 350,
                  minWidth: 350,
                  visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
              },

              {
                  title: '问题&风险',
                  dataIndex: 'question',
                  ellipsis: true,
                  align: 'center',
                  resizable: true,
                  width: 350,
                  minWidth: 350,
                  visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
              },
              {
                  title: '风险等级',
                  dataIndex: 'riskLevel',
                  align: 'center',
                  ellipsis: true,
                  width: 120,
                  visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
              },
              {
                  title: '项目支持',
                  dataIndex: 'supportors',
                  align: 'center',
                  ellipsis: true,
                  width: 120,
                  visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
              },
              {
                  title: '正式运行持续天数',
                  dataIndex: 'runDays',
                  align: 'center',
                  ellipsis: true,
                  width: 120,
                  visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
              },
              {
                  title: '综合样20次',
                  dataIndex: 'comprehensiveSample',
                  align: 'center',
                  ellipsis: true,
                  width: 120,
                  visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
              },
              {
                  title: '降本空间',
                  dataIndex: 'expectedCostReduction',
                  align: 'center',
                  ellipsis: true,
                  width: 120,
                  visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
              },
              {
                  title: '生产计划',
                  dataIndex: 'productionPlan',
                  resizable: true,
                  align: 'center',
                  ellipsis: true,
                  width: 350,
                  minWidth: 350,
                  visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
              },
              {
                  title: '客情关系',
                  dataIndex: 'customerRelationship',
                  resizable: true,
                  align: 'center',
                  ellipsis: true,
                  width: 350,
                  minWidth: 350,
                  visible: computed(() => ['全部', '其他'].includes(ftfState.radioValue))
              }
              // 其他通用列
          ],
          newColumns: [
              {
                  title: '',
                  dataIndex: 'name',
                  align: 'center',
                  fixed: 'left',
                  ellipsis: true
              },

              {
                  title: '数据积累',
                  ellipsis: true,
                  dataIndex: 'dataCollector',
                  align: 'center'
              },

              {
                  title: '自学习表数据确认',
                  width: 150,
                  ellipsis: true,
                  dataIndex: 'selfLearnConfirm',
                  align: 'center'
              },
              {
                  title: '数据建模',
                  ellipsis: true,
                  dataIndex: 'modeling',
                  align: 'center'
              },
              {
                  title: '试运行',
                  ellipsis: true,
                  dataIndex: 'testRun',
                  align: 'center'
              },
              {
                  title: '正式运行',
                  ellipsis: true,
                  dataIndex: 'run',
                  align: 'center'
              },
              {
                  title: '验证',
                  ellipsis: true,
                  dataIndex: 'verify',
                  align: 'center'
              },
              {
                  title: '验收',
                  dataIndex: 'check',
                  ellipsis: true,
                  align: 'center'
              }
          ]
      })
      const ftfState = reactive({
          detailVisible: false,
          modalVisible: false,
          radioValue: '全部',
          dataSource: [],
          tableLoading: false,
          filter: {
              areaName: undefined,
              projectDirector: undefined,
              projectId: undefined,
              batch: undefined,
              milepostName: undefined,
              riskLevel: [],
              projectStatus: undefined,
              customSort: {
                  'sortDirection': 'ASC',
                  'filed': 'AREA'
              }
              // milepostOrder: false
          },
          checkList: ['计划开始', '计划结束', '实际开始', '实际结束', '预计开始', '预计结束'],
          baseCheckList: ['批次', '产品类型', '项目总监', '水泥专家', '项目经理', '算法', '商务', '项目阶段', '项目状态'],
          milepostCheckList: [],
          // milepostCheckList: ['验收', '验证', '正式运行', '试运行', '数据建模', '自学习表数据确认', '数据积累'],
          otherCheckList: [
              '进展',
              '问题风险',
              '风险等级',
              '项目支持',
              '正式运行持续天数',
              '综合样20次',
              '降本空间',
              '生产计划',
              '客情关系'
          ],
          settingVisible: false,
          activeKey: '基础信息'
      })
      const handleTableChange = (pagination, filters, sorter) => {
          let currentSortDirection = 'ASC' // 默认排序方向为 ASC
          let currentField = 'AREA' // 默认字段为 AREA

          if (sorter.column && sorter.column.dataIndex === 'milepostName') {
              // 判断排序方向
              if (sorter.order === 'ascend') {
                  currentSortDirection = 'ASC'
              } else if (sorter.order === 'descend') {
                  currentSortDirection = 'DESC'
              }
              // 设置自定义排序
              ftfState.filter.customSort = {
                  sortDirection: currentSortDirection,
                  filed: 'MILEPOST' // 根据需要修改字段名
              }
          } else {
              // 如果没有对 'milepostName' 进行排序，使用默认排序
              ftfState.filter.customSort = {
                  sortDirection: currentSortDirection,
                  filed: currentField
              }
          }
          getLcbData()
      }
      // 原里程碑进度部分
      const apiMap = {
          '任务完成': '/solution-ppm/api/v2/built-in-system-ppm/project/dashboard/operation/task_search',
          '资源投入': '/solution-ppm/api/v2/built-in-system-ppm/project/dashboard/operation/resource_search',
          '成本统计': '/solution-ppm/api/v2/built-in-system-ppm/project/dashboard/operation/cost_search'
      }
      function getData(item, id, type, areaName) {
          if (type !== '水泥配料') {
              return
          }
          ftfState.filter.projectId = id
          ftfState.tableLoading = true
          post(apiMap[typeList.value[typeSelectIndex.value].itemName], {
              productLine: proList.value[proSelectIndex.value].itemName,
              type: typeList.value[typeSelectIndex.value].type,
              projectId: id
          })
              .then(data => {
                  if (data.code !== 200) {
                      ftfState.dataSource = {}
                      message.error(data.message)
                      return
                  }
                  let dataNew = {
                      ...data.data,
                      rippleEffect: item.rippleEffect,
                      deviation: item.deviation
                  }
                  ftfState.dataSource = dataNew
                  ftfState.detailVisible = true
              })
              .finally(() => {
                  ftfState.tableLoading = false
              })
      }
      // 里程碑进度表弹窗
      const newState = reactive({
          priority: '全部'
      })
      function changeSymbelSize() {
          // ongetoperation({
          //     productLine: proList.value[proSelectIndex.value].itemName,
          //     type: typeList.value[typeSelectIndex.value].type
          // })
          renderChart()
      }
      function getOverExpenditure(totalPeriodDeviation) {
          if (totalPeriodDeviation == 0) {
              return '未超支'
          } else if (totalPeriodDeviation > 0) {
              return `超支${totalPeriodDeviation}%`
          } else if (totalPeriodDeviation < 0) {
              return '未超支'
          }
      }
      function getCostColor(item, flag) {
          console.log(item)
          if (item === null || item === undefined) {
              return {
                  color: flag ? '#595959' : '#262626'
              }
          } else if (item > 0) {
              return {
                  color: '#F5222D'
              }
          } else if (item <= 0) {
              return {
                  color: '#52C41A'
              }
          }
      }
      function getTotalCostColor(item, flag) {
          if (item === null || item === undefined) {
              return {
                  color: flag ? '#595959' : '#262626'
              }
          } else if (item > 0) {
              return {
                  color: '#F5222D'
              }
          } else if (item <= 0) {
              return {
                  color: '#52C41A'
              }
          }
      }
      function getCostDiffer() {
          if (ftfState.dataSource.costDeviation === 0) {
              return '未超支'
          }
          if (ftfState.dataSource.costDeviation > 0) {
              return `超支${ftfState.dataSource.costDeviation}%`
          } else if (ftfState.dataSource.costDeviation < 0) {
              return '未超支'
          }
      }
      function getTaskStatus(data) {
          if (data === 0 || data < 0) {
              return '未超期'
          } else if (data > 0) {
              return `延期${data}%`
          } else if (!data) {
              return '--'
          }
      }
      function getTotalTaskStatus(data) {
          if (data === 0 || data < 0) {
              return '未超期'
          } else if (data > 0) {
              return `延期${data}%`
          } else if (!data) {
              return '--'
          }
      }

      //     成本基准
      function getReferenceColor(item, flag) {
          if (item === null || item === undefined) {
              return {
                  color: flag ? '#595959' : '#262626'
              }
          } else if (item > 0) {
              return {
                  color: '#F5222D'
              }
          } else if (item <= 0) {
              return {
                  color: '#52C41A'
              }
          }
      }
      // 累计周期偏差
      function getTotalReferenceColor(item, flag) {
          if (item === null || item === undefined) {
              return {
                  color: flag ? '#595959' : '#262626'
              }
          } else if (item > 0) {
              return {
                  color: '#F5222D'
              }
          } else if (item <= 0) {
              return {
                  color: '#52C41A'
              }
          }
      }
      // 新-模板项目审核标准格式
      function handlerGetSpace(data) {
          return data?.split(/[;；]/)
      }
      function getNameColor(num, flag) {
          if (num === null || num === undefined) {
              return
          }
          const colors = ['#52c41a', '#ffc500', '#f5222d']
          const index = num < 21 ? 0 : num > 50 ? 2 : 1
          return {
              color: colors[index]
          }
      }
</script>
<style lang="less" scoped>
  .page_root {
  width: 100%;
  height: 100%;
  overflow: auto;
  }
  .page_root :deep(.@{ant-prefix}-spin-nested-loading),
  .page_root :deep(.@{ant-prefix}-spin-container)
   {
      height: 100%;
  }
  .page_root :deep(.@{ant-prefix}-spin-container .@{ant-prefix}-table-wrapper)
   {
      display: flex;
      flex-flow: column nowrap;
      justify-content: flex-start;
  }
  .page_root :deep(.@{ant-prefix}-table)
   {
    flex: auto;
    overflow: auto;
  }
  .table-moreBtn_down {
    overflow: hidden; white-space: nowrap; text-overflow: ellipsis; width: 100px;
  }

  .table-moreBtn_menu :deep(.table-moreBtn_menu-item):hover {
    background: #ebf1ff;
  }

  /*  表格树结构样式处理，展开按钮层级增加*/
  :deep(.@{ant-prefix}-table-row-expand-icon) {
    z-index: 1;
  }
  /*  表格树结构 由于每个表格项采用自定义组件，使用绝对定位布局，开启树结构导致显示异常，暂时使用层级定位位置 */
  :deep(.@{ant-prefix}-table-row-level-1 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 15px !important;
    width: calc(100% - 15px);
  }
  :deep(.@{ant-prefix}-table-row-level-2 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 30px !important;
    width: calc(100% - 30px);
  }
  :deep(.@{ant-prefix}-table-row-level-3 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 45px !important;
    width: calc(100% - 45px);
  }
  :deep(.@{ant-prefix}-table-row-level-4 .@{ant-prefix}-table-cell-with-append .cell-wrapper-left) {
    left: 60px !important;
    width: calc(100% - 60px);
  }

  /* 穿梭框改变默认样式，为根据组件样式控制左右栏宽度。 */
  :deep(.@{ant-prefix}-transfer-list)
   {
      height: 100%;
      width: 50%;
  }


  .img {
          display: inline-block;
          background-size: 100%;
          background-repeat: no-repeat;
      }
      .icon-green {
          background: url('@/assets/images/6ab2616ca12628e10d3c4ced66ef6d3d.svg');
      }
      .icon-yellow {
          background: url('@/assets/images/fea33e9131eb91976ed6122af567c76a.svg');
      }
      .icon-red {
          background: url('@/assets/images/b42a435f229f0bd0476d1499f8ee758c.svg');
      }
      .icon-data-sel {
          background: url('@/assets/images/222c56eae980a7215f762a8960fbead0.svg');
      }
      .icon-data {
          background: url('@/assets/images/c7320314e7e82ee8cf2e9bdc637dfbd6.svg');
      }
      .icon-pro {
          background: url('@/assets/images/89f0b358f8e057d5cb90e524acdf429e.svg');
      }
      .icon-pro-sel {
          background: url('@/assets/images/5663d7925478b17654621f717f6305bb.svg');
      }
      .icon-area {
          background: url('@/assets/images/8775dc8f36eacfd4e7452d828abf1be9.svg');
      }
      .icon-area-sel {
          background: url('@/assets/images/af9d47c90bff15ffbb5fecf2021e84ed.svg');
      }
      .icon-more {
          background: url('@/assets/images/6be604a73baba7651efb497101b0b964.svg');
      }
      .icon-more-sel {
          background: url('@/assets/images/8584ef8767de5f3efddfc0b9c6ec39b1.svg');
      }
      ul,
      li {
          padding: 0;
          margin: 0;
      }
      .top-title {
          height: 64px;
          background: url('@/assets/images/242a94e86ef48d58300b724953fd3631.svg');
          background-size: contain;
          background-position: center;
          background-repeat: no-repeat;
          display: flex;
          justify-content: center;
          align-items: center;
          font-family: PingFangSC-Semibold;
          font-size: 36px;
          color: #ffffff;
          letter-spacing: 10px;
          font-weight: 600;
      }
      .left-geo {
          position: absolute;
          cursor: pointer;
          z-index: 999;
          top: -24px;
          left: 16px;
          bottom: 24px;
          display: flex;
          flex-direction: column;
          li {
              line-height: 100%;
          }
          .proAreaSels {
              background-image: linear-gradient(179deg, rgba(218, 237, 255, 0.4) 0%, rgba(242, 253, 255, 0.4) 100%);
              box-shadow: 0 2px 10px 0 #d5e7ed;
              border-radius: 4px;
              border: 1px solid;
              border-image: linear-gradient(to bottom, #3875ff, #fff, #fff, #3875ff) 1;
              padding: 16px;
              max-width: 240px;
              min-width: 200px;
              width: 12vw;
              box-sizing: border-box;
              margin-top: 16px;
              flex: 1;
              .icon.img {
                  width: 16px;
                  height: 16px;
              }

              .unexpend {
                  li {
                      display: none;
                  }
                  .arrow-right {
                      transform: rotate(90deg);
                  }
              }
              .show-active {
                  display: none;
              }
              .active {
                  .arrow-right {
                      border-left: 8px solid #3875ff;
                  }
                  .show-active {
                      display: unset;
                  }
                  .hide-active {
                      display: none;
                  }
              }
              .name {
                  border-radius: 2px;
                  height: 32px;
                  display: flex;
                  align-items: center;
                  padding: 0 9px;
                  font-family: PingFangSC-Semibold;
                  font-size: 16px;
                  letter-spacing: 0;
                  line-height: 32px;
                  font-weight: 600;
                  &.active {
                      background: rgba(56, 117, 255, 0.1);
                      color: #3875ff;
                      .arrow-right {
                          border-left: 8px solid #3875ff;
                      }
                  }
              }
              .icon {
                  margin-right: 4px;
              }
              .arrow-right {
                  display: inline-block;
                  border-left: 8px solid #8c8c8c;
                  border-top: 6px solid transparent;
                  border-bottom: 6px solid transparent;
                  transform: rotate(0deg);
              }
              li {
                  display: flex;
                  line-height: 32px;
                  align-items: center;
                  padding-left: 39px;
                  font-family: PingFangSC-Regular;
                  font-size: 14px;
                  color: #595959;
                  letter-spacing: 0;
                  line-height: 32px;
                  font-weight: 400;
                  &.active {
                      background: rgba(56, 117, 255, 0.1);
                      color: #3875ff;
                  }
                  &.disabled {
                      font-family: PingFangSC-Regular;
                      font-size: 14px;
                      color: #acacac;
                      letter-spacing: 0;
                      line-height: 32px;
                      font-weight: 400;
                      cursor: not-allowed;
                  }
              }
          }
          .typeSels {
              position: relative;
              background: #ffffff;
              border: 1px solid #3875ff;
              border-radius: 4px;
              font-size: 14px;
              color: #262626;
              letter-spacing: 0;
              text-align: center;
              line-height: 20px;
              font-weight: 400;
              display: inline-flex;
              width: 267px;
              li {
                  flex: 1;
                  display: inline-block;
                  padding: 6px 16px;
                  line-height: 20px;
                  white-space: nowrap;
                  &.action {
                      background: #3875ff;
                      color: #fff;
                  }
              }
              li:nth-child(-n + 2) {
                  border-right: 1px solid #3875ff;
              }
              .priority-div {
                  position: absolute;
                  right: -176px;
                  :deep(.ant3-select:not(.ant3-select-customize-input) .ant3-select-selector) {
                      border-color: #3875ff;
                      color: #3875ff;
                      text-align: left;
                  }
                  :deep(.ant3-select-arrow) {
                      color: #3875ff;
                  }
              }
          }
      }
      .main-content {
          width: 100%;
          height: 100%;
          overflow: hidden;
          position: relative;
          background-color: #fff;
          //border: 1px solid blue;
          background: url('@/assets/images/4e5500102dd3b5f283a2d424790207ff.svg');
          background-size: cover;
          background-repeat: no-repeat;
          background-position: center;
          * {
              user-select: none;
              -webkit-user-select: none; /* Safari */
              -moz-user-select: none; /* Firefox */
              -ms-user-select: none; /* IE 10 and IE 11 */
          }
      }
      .content {
          padding: 0 16px;
          display: flex;
          justify-content: center;
          position: relative;
      }
      .echarts-content {
          margin-left: 7%;
          //border: 1px solid red;
          width: 1126px;
          height: 794px;
          position: relative;
          //border: 1px solid red;
          overflow: hidden;
          //transform: scale(1, 0.96);
          //transform: scale(1, 0.87);
          transform-origin: 0 0;
          .china-map-bg {
              position: absolute;
              top: 40px;
              left: 112px;
              width: 898px;
              height: 634px;
              transform: scale(1, 1.152);
              transform-origin: top;
              background: url('@/assets/images/0e9e661eaef818459b7aeba4247efe31.svg');
              background-size: cover;
          }
      }
      .legend {
          position: absolute;
          display: flex;
          align-items: center;
          justify-content: center;
          width: 100%;
          margin-top: 16px;
          z-index: 9;
          li {
              display: flex;
              align-items: center;
              margin: 0 12px;
              cursor: pointer;
              &.gray {
                  opacity: 0.56;
              }
              .icon {
                  width: 24px;
                  height: 24px;
                  margin-right: 8px;
              }
          }
      }
      .echarts-main {
          width: 1126px;
          height: 2000px;
          position: relative;
          transform: translateY(-472px);
      }
      .fill {
          color: red;
      }

      ::v-deep .map-dialog {
          background: #ffffff;
          border: 1px solid #3875ff !important;
          box-shadow: 0 4px 0 0 rgba(56, 117, 255, 0.64) !important;
          border-radius: 2px 2px 2px 0 0 0 2px !important;
          font-family: PingFangSC-Regular;
          font-size: 14px !important;
          color: #262626 !important;
          letter-spacing: 0 !important;
          text-align: center !important;
          font-weight: 400 !important;

          .value {
              font-size: 10px;
          }
          .status-0 {
              .value {
                  color: #52c41a;
              }
          }
          .status-1 {
              .value {
                  color: #ff8c00;
              }
          }
          .status-2 {
              .value {
                  color: #f5222d;
              }
          }
      }

      ::v-deep .map-dialog::after,
      ::v-deep .map-dialog::before {
          content: '';
          position: absolute;
          bottom: -10px; /* 箭头的顶部位置，负数表示向上移动 */
          left: 50%; /* 箭头的水平中心位置 */
          margin-left: -10px; /* 将箭头水平居中对齐 */
          width: 0;
          height: 0;
          border-left: 10px solid transparent; /* 左边框透明 */
          border-right: 10px solid transparent; /* 右边框透明 */
          border-top: 10px solid #fff; /* 底边框设置箭头颜色和大小 */
      }

      ::v-deep .map-dialog::before {
          margin-left: -16px; /* 将箭头水平居中对齐 */
          bottom: -16px; /* 箭头的顶部位置，负数表示向上移动 */
          border-left: 16px solid transparent; /* 左边框透明 */
          border-right: 16px solid transparent; /* 右边框透明 */
          border-top: 16px solid rgba(56, 117, 255, 0.64); /* 底边框设置箭头颜色和大小 */
      }

      /*
  里程碑进度表样式
  */
      /*冯腾飞样式*/
      .kb-table-box:deep(.@{ant-prefix}-table-thead) > tr > th {
          background: #3875ff;
          color: #fff;
          font-weight: 600;
          padding: 8px 16px;
          border-right: 1px solid #d9d9d9 !important;
          position: relative;
      }
      .kb-table-box :deep(.@{ant-prefix}-table-tbody) tr > td {
          font-size: 14px;
          font-family: arial, helvetica, 'microsoft yahei';
          font-weight: 400;
          color: #262626;
          border-bottom: 1px solid #d9d9d9;
          padding: 8px 16px;
          word-break: break-all;
      }
      .search-radio {
          margin-bottom: 16px;
      }
      .db-click-name {
          width: 120px;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
          height: 30px;
          line-height: 30px;
      }
      .omit-div,
      .omit-div-question,
      .omit-div-productionPlan,
      .omit-div-customerRelationship {
          width: 320px;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
          height: 100%;
          padding: 0 8px;
      }
      .plus-icon {
          position: absolute;
          right: 0;
          top: 0;
          cursor: pointer;
      }
      .progress-click {
          height: 30px;
          line-height: 30px;
          cursor: pointer;
          display: flex;
      }
      :deep(.ant3-modal-header) {
          padding: 0;
          border: none;
      }
      .modal-body {
          height: 800px;
          overflow-y: auto;
          background-image: url('@/assets/images/83b6d1da6a45a94bfef276858b6c9cec.png');
          background-size: cover;
          padding: 32px;
          padding-bottom: 0;
      }
      .modal-top {
          display: flex;
          gap: 24px;
          margin-bottom: 24px;
          .modal-top-left {
              height: 138px;
              background: rgba(255, 255, 255, 0.75);
              border: 2px solid #ffffff;
              border-radius: 4px;
              padding: 16px 24px;

              .left-top {
                  display: flex;
                  margin-bottom: 4px;
                  .left-top-img {
                      background-size: cover;
                      height: 20px;
                      width: 20px;
                      background-image: url('@/assets/images/f2c9dd114242afd9167d6cf6adf891ca.png');
                  }
                  .left-top-msg {
                      font-size: 16px;
                      color: #262626;
                      letter-spacing: 0;
                      font-weight: 500;
                  }
              }
              .left-bottom {
                  display: flex;
                  flex-direction: row;
                  gap: 48px;
                  .bottom-left {
                      width: 50%;
                      display: flex;
                      gap: 4px;
                      flex-direction: column;
                      .bottom-left-item {
                          display: flex;
                          .title {
                              font-size: 14px;
                              color: #595959;
                              letter-spacing: 0;
                              font-weight: 400;
                              white-space: nowrap;
                          }
                          .msg {
                              font-size: 14px;
                              color: #262626;
                              letter-spacing: 0;
                              font-weight: 500;
                              white-space: nowrap;
                          }
                      }
                  }
                  .bottom-right {
                      position: relative;
                      flex: 1;
                      display: flex;
                      gap: 4px;
                      flex-direction: column;
                      .route {
                          background-size: cover;
                          height: 76px;
                          width: 1px;
                          background-image: url('@/assets/images/677043658fcaadf4608998a7d9caef84.png');
                          position: absolute;
                          top: 58%;
                          left: -24px;
                          transform: translate(-50%, -50%);
                      }
                      .bottom-right-item {
                          display: flex;
                          .title {
                              font-size: 14px;
                              color: #595959;
                              letter-spacing: 0;
                              font-weight: 400;
                              white-space: nowrap;
                          }
                          .msg {
                              font-size: 14px;
                              color: #262626;
                              letter-spacing: 0;
                              font-weight: 500;
                              white-space: nowrap;
                          }
                      }
                  }
                  .normal {
                      color: #262626;
                  }
                  .exceed {
                      color: #f5222d;
                  }
              }
          }
          .modal-top-right {
              width: 260px;
              height: 138px;
              background: rgba(255, 255, 255, 0.75);
              border: 2px solid #ffffff;
              border-radius: 4px;
              padding: 16px 24px;
              .right-top {
                  gap: 8px;
                  display: flex;
                  margin-bottom: 4px;
                  align-items: center;
                  .right-top-img {
                      background-size: cover;
                      height: 20px;
                      width: 20px;
                      background-image: url('@/assets/images/769d87db636504cc9f75acde9c58b553.png');
                  }
                  .right-top-msg {
                      font-size: 16px;
                      color: #262626;
                      letter-spacing: 0;
                      font-weight: 500;
                  }
              }
              .right-bottom {
                  display: flex;
                  flex-direction: column;
                  gap: 4px;
                  .bottom-right-item {
                      display: flex;
                      .title {
                          font-size: 14px;
                          color: #595959;
                          letter-spacing: 0;
                          font-weight: 400;
                          white-space: nowrap;
                      }
                      .msg {
                          font-size: 14px;
                          color: #262626;
                          letter-spacing: 0;
                          font-weight: 500;
                          white-space: nowrap;
                      }
                  }
              }
          }
      }
      .kb-table-box {
          background: rgba(255, 255, 255, 0.75);
          border: 2px solid #ffffff;
          border-radius: 4px;
          padding: 16px 24px;
          .inner-table {
              background: rgba(255, 255, 255, 0.5);
              border: 1px solid #3875ff;
              border-radius: 4px;
              padding: 16px 24px;
              .inner-top-main {
                  margin-bottom: 4px;
                  display: flex;
                  .inner-top-item {
                      display: flex;
                      flex-direction: column;
                      gap: 8px;
                      flex-grow: 1;
                      .item-son {
                          display: flex;
                          justify-content: flex-start;
                          .risk-level-tool-tip {
                              margin: 0;
                          }
                          .title {
                              font-size: 14px;
                              color: #595959;
                              letter-spacing: 0;
                              font-weight: 400;
                              white-space: nowrap;
                          }
                          .msg {
                              font-size: 14px;
                              color: #262626;
                              letter-spacing: 0;
                              font-weight: 500;
                              white-space: nowrap;
                          }
                      }
                  }
              }
              .inner-row {
                  margin-bottom: 8px;
                  display: flex;
                  .title {
                      font-size: 14px;
                      color: #595959;
                      letter-spacing: 0;
                      font-weight: 400;
                      white-space: nowrap;
                      white-space: nowrap;
                  }
                  .msg {
                      font-size: 14px;
                      color: #262626;
                      letter-spacing: 0;
                      font-weight: 500;
                  }
              }
          }
      }
      .modal-top-0 {
          display: flex;
          gap: 24px;
          margin-bottom: 24px;
          .modal-top-left-0 {
              height: 138px;
              background: rgba(255, 255, 255, 0.75);
              border: 2px solid #ffffff;
              border-radius: 4px;
              padding: 16px 24px;

              .left-top-0 {
                  display: flex;
                  margin-bottom: 4px;
                  .left-top-img {
                      background-size: cover;
                      height: 20px;
                      width: 20px;
                      background-image: url('@/assets/images/f2c9dd114242afd9167d6cf6adf891ca.png');
                  }
                  .left-top-msg {
                      font-size: 16px;
                      color: #262626;
                      letter-spacing: 0;
                      font-weight: 500;
                  }
              }
              .left-bottom-0 {
                  display: flex;
                  gap: 16px;
                  flex-direction: row;
                  .new-bottom {
                      display: flex;

                      gap: 48px;
                  }
                  .bottom-left-0 {
                      width: 55%;
                      display: flex;
                      gap: 4px;
                      flex-direction: column;
                      .bottom-left-item {
                          display: flex;
                          .title {
                              font-size: 14px;
                              color: #595959;
                              letter-spacing: 0;
                              font-weight: 400;
                              white-space: nowrap;
                          }
                          .msg {
                              font-size: 14px;
                              color: #262626;
                              letter-spacing: 0;
                              font-weight: 500;
                              white-space: nowrap;
                          }
                      }
                  }
                  .bottom-right-0 {
                      flex: 1;
                      display: flex;
                      gap: 4px;
                      flex-direction: column;
                      position: relative;
                      .route-0 {
                          background-size: cover;
                          height: 76px;
                          width: 1px;
                          background-image: url('@/assets/images/677043658fcaadf4608998a7d9caef84.png');
                          position: absolute;
                          top: 58%;
                          left: -24px;
                          transform: translate(-50%, -50%);
                      }
                      .bottom-right-item {
                          display: flex;
                          .title {
                              font-size: 14px;
                              color: #595959;
                              letter-spacing: 0;
                              font-weight: 400;
                              white-space: nowrap;
                          }
                          .msg {
                              font-size: 14px;
                              color: #262626;
                              letter-spacing: 0;
                              font-weight: 500;
                              white-space: nowrap;
                          }
                      }
                  }
                  .bottom-right-last-0 {
                      .bottom-right-item {
                          display: flex;
                          .title {
                              font-size: 14px;
                              color: #595959;
                              letter-spacing: 0;
                              font-weight: 400;
                              white-space: nowrap;
                          }
                          .msg {
                              font-size: 14px;
                              color: #262626;
                              letter-spacing: 0;
                              font-weight: 500;
                              white-space: nowrap;
                          }
                      }
                  }
                  .normal {
                      color: #262626;
                  }
                  .exceed {
                      color: #f5222d;
                  }
              }
          }
          .modal-top-right-0 {
              width: 260px;
              height: 138px;
              background: rgba(255, 255, 255, 0.75);
              border: 2px solid #ffffff;
              border-radius: 4px;
              padding: 16px 24px;
              .right-top-0 {
                  gap: 8px;
                  display: flex;
                  margin-bottom: 4px;
                  align-items: center;
                  .right-top-img {
                      background-size: cover;
                      height: 20px;
                      width: 20px;
                      background-image: url('@/assets/images/769d87db636504cc9f75acde9c58b553.png');
                  }
                  .right-top-msg-0 {
                      font-size: 16px;
                      color: #262626;
                      letter-spacing: 0;
                      font-weight: 500;
                  }
              }
              .right-bottom-0 {
                  display: flex;
                  flex-direction: column;
                  gap: 4px;
                  .bottom-right-item-0 {
                      display: flex;
                      .title {
                          font-size: 14px;
                          color: #595959;
                          letter-spacing: 0;
                          font-weight: 400;
                          white-space: nowrap;
                      }
                      .msg {
                          font-size: 14px;
                          color: #262626;
                          letter-spacing: 0;
                          font-weight: 500;
                          white-space: nowrap;
                      }
                  }
              }
          }
      }

      .kb-table-box-new:deep(.@{ant-prefix}-table-thead) > tr > th {
        background: #3875ff;
        color: #fff;
        font-weight: 600;
        padding: 0;
        border-right: 1px solid #d9d9d9 !important;
        position: relative;
      }
      .kb-table-box-new :deep(.@{ant-prefix}-table-tbody) tr > td {
        font-size: 14px;
        font-family: arial, helvetica, 'microsoft yahei';
        font-weight: 400;
        color: #262626;
        border-bottom: 1px solid #d9d9d9;
        padding: 0 5px;
        word-break: break-all;
      }
      /*冯腾飞样式*/
</style>